package com.navinfo.opentsp.platform.computing.analysis.service;

import com.navinfo.opentsp.platform.computing.analysis.entity.disconnectedVehicle.OutStatusDto;
import com.navinfo.opentsp.platform.computing.analysis.entity.disconnectedVehicle.PointForDisconnectAnalysis;
import com.navinfo.opentsp.platform.computing.analysis.util.DateUtils;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;

public class DisconnectedVehicleAlgorithmService implements Serializable {
    /**
     * 个别算法只判断5天内的0200点
     */
    private static final int DAYS = 5;
    private static final long MILLI_SEC_PER_DAY = 24 * 60 * 60 * 1000;

    private final List<Algorithm> algorithms;
    private final long timestamp;

    public DisconnectedVehicleAlgorithmService(String day) {
        this.algorithms = Arrays.asList(new LackOfElectricity(), new Modified(), new PoorSignal(), new AbnormalDisconnection(),
                new LongStayDisconnection(), new SaveAlarm());

        this.timestamp = DateUtils.getNextDayBeginTime(DateUtils.convertYYYYMMDD(day)) - DAYS * MILLI_SEC_PER_DAY;
    }

    public void dealPoint(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
        for (Algorithm a : algorithms) {
            a.execute(point, outStatus);
        }
        // 保存上一个点信息
        outStatus.setLastSignalStrength(point.getSignalStrength());
        outStatus.setLastRotation2(outStatus.getLastRotation());
        outStatus.setLastRotation(point.getRotation());
    }

    interface Algorithm {
        void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus);
    }

    class LackOfElectricity implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 电瓶亏电：5天 先欠压报警，后掉电报警
            if (point.getGpsTime() < timestamp) {
                return;
            }
            if (outStatus.getUndervoltageFlag() == 1) {
                // 已经是出现过欠压报警的状态
                if (point.getPowerDown() == 1) {
                    outStatus.setLackOfElectricity();
                }
            } else {
                // 没出现过欠压报警
                if (point.getUndervoltage() == 1) {
                    outStatus.setUndervoltageFlag(1);
                }
            }
        }
    }

    class Modified implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 用户改装：5天 有“accOff + 掉电报警 + 不欠压报警”的点
            if (point.getGpsTime() < timestamp) {
                return;
            }
            if (point.getAccStatus() == 0 && point.getPowerDown() == 1 && point.getUndervoltage() == 0) {
                outStatus.setModified();
            }
        }
    }

    class PoorSignal implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 信号弱：5天 最后一个点和倒数第二个点的信号强度<16
            if (point.getGpsTime() < timestamp) {
                return;
            }
            final int threshold = 16;
            if (outStatus.isLast() && outStatus.getLastSignalStrength() < threshold && point.getSignalStrength() < threshold) {
                outStatus.setPoorSignal();
            }
        }
    }

    class AbnormalDisconnection implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 异常断连：7天 存在连续3个点发动机转速>500
            if (!outStatus.isAbnormalDisconnection()) {
                final int threshold = 500;
                if (outStatus.getLastRotation2() >= threshold && outStatus.getLastRotation() >= threshold && point.getRotation() >= threshold) {
                    outStatus.setAbnormalDisconnection();
                }
            }
        }
    }

    class LongStayDisconnection implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 长停断连：7天 不存在连续3个点发动机转速>500
            if (outStatus.isLast() && !outStatus.isAbnormalDisconnection()) {
                outStatus.setLongStayDisconnection();
            }
        }
    }

    class SaveAlarm implements Algorithm, Serializable {
        @Override
        public void execute(PointForDisconnectAnalysis point, OutStatusDto outStatus) {
            // 保存最后一个不为0的报警标志位
            if (point.getAlarm() != 0) {
                outStatus.setAlarm(point.getAlarm());
            }
        }
    }
}
